use crate::cli::package::cache::package_cache;
use crate::cli::package::delete::package_delete;
use crate::cli::package::download::package_download;
use crate::cli::package::init::package_init;
use crate::cli::package::list::package_list;
use crate::cli::package::make::package_make;
use crate::cli::package::publish::package_publish;
use crate::cli::package::query::package_query;
use crate::cli::package::update::package_update;
use clap::Subcommand;

#[derive(Subcommand, Debug, Clone)]
pub enum PackageSubcommand {
    ///包初始化操作;
    ///该指令用于在项目目录下初始化包规范文件，该文件用于制作软件包。
    Init {
        ///待初始化包的源目录(必选);
        ///该目录一般为项目目录。
        #[arg(short, long, default_value = "./")]
        src_dir: String,
    },
    ///包更新操作。
    Update {
        ///更新类型(必选);
        ///支持的更新类型有：1. toolchain。
        ///2. library。
        #[arg(short='t', long, value_parser = check_update_type)]
        update_type: String,
        ///包ID(可选);
        ///当设置更新类型为【library】时，需指定该参数;
        #[arg(short, long)]
        pkg_id: Option<String>,
        ///版本号(可选);
        ///当设置更新类型为【library】时，不指定该参数默认更新最新版本;
        #[arg(short, long)]
        version: Option<String>,
        ///项目目录(可选);
        ///当设置更新类型为【library】时，需指定该参数;
        #[arg(short, long)]
        project_dir: Option<String>,
        ///体系架构(可选);
        ///当设置更新类型为【toolchain】时，需指定该参数;
        ///若不指定，则默认为【arm】。
        #[arg(short, long, default_value = "arm")]
        arch: Option<String>,
    },
    ///制作软件包。
    Make {
        ///指定制作包模式(必选);
        ///可选值有：1.对话模式：dialog，该模式下用户信息以交互式控制台方式传入；
        ///        2.直接模式：direct，读取pkg.spec配置文件，直接制作包。
        #[arg(short, long, value_parser = check_make_mode)]
        mode: String,
        ///待制作包的源目录(可选);
        ///该目录一般为项目目录；
        ///若未指定，则默认为当前目录。
        #[arg(short, long, default_value = "./")]
        spec_dir: Option<String>,
    },
    ///发布软件包。
    Publish {
        ///待发布的软件包路径(必选)。
        #[arg(short, long)]
        pkg_path: String,
    },
    ///查询软件包。
    Query {
        ///待查询包的名称(可选);
        ///若未指定，则默认查询所有包。
        #[arg(short, long)]
        pkg_name: Option<String>,
    },
    ///下载软件包。
    Download {
        ///待查询包的标识(必选)。
        #[arg(short, long)]
        pkg_id: String,
        ///软件包版本号(可选, 默认为最新版本)。
        #[arg(short, long)]
        version: Option<String>,
        ///项目目录(可选)。
        ///默认为缓存目录，可通过dio project bind加载软件包到项目。
        #[arg(short = 'P', long)]
        project_dir: Option<String>,
    },
    ///列出软件包。
    List {
        ///以json格式输出项目信息(可选)。
        ///若未指定，默认以键值对格式输出
        #[arg(short, long)]
        json: Option<bool>,
        ///指定项目名称(可选)
        #[arg(short, long)]
        name: Option<String>,
        ///指定库文件类型,多个类型用逗号分隔(可选);
        ///可选值有sample，static，dynamic。
        #[arg(short='t', long, value_parser = check_list_type)]
        lib_type: Option<String>,
    },
    ///列出已下载软件包。
    Cache {
        ///以json格式输出项目信息(可选)。
        ///若未指定，默认以键值对格式输出
        #[arg(short, long)]
        json: Option<bool>,
        ///指定项目名称(可选)
        #[arg(short, long)]
        name: Option<String>,
    },
    ///删除软件包。
    Delete {
        ///项目目录(必选)
        #[arg(short, long)]
        project_dir: String,
    },
}

fn check_make_mode(mode: &str) -> Result<String, String> {
    match mode {
        "dialog" => Ok("dialog".to_string()),
        "direct" => Ok("direct".to_string()),
        _ => Err("不支持的制作模式!".to_string()),
    }
}

fn check_list_type(lib_type: &str) -> Result<String, String> {
    match lib_type {
        "sample" => Ok("sample".to_string()),
        "static" => Ok("static".to_string()),
        "dynamic" => Ok("dynamic".to_string()),
        _ => Err("不支持的软件包类型!".to_string()),
    }
}

fn check_update_type(update_type: &str) -> Result<String, String> {
    match update_type {
        "toolchain" => Ok("toolchain".to_string()),
        "library" => Ok("library".to_string()),
        _ => Err("不支持的升级类型!".to_string()),
    }
}

pub fn package_run(cmd: PackageSubcommand) {
    if let cmd = cmd {
        match cmd {
            PackageSubcommand::Init { src_dir } => package_init(src_dir),
            PackageSubcommand::Update {
                update_type,
                pkg_id,
                version,
                project_dir,
                arch,
            } => package_update(update_type, pkg_id, version, project_dir, arch),
            PackageSubcommand::Make { mode, spec_dir } => package_make(mode, spec_dir),
            PackageSubcommand::Publish { pkg_path } => package_publish(pkg_path),
            PackageSubcommand::Query { pkg_name } => package_query(pkg_name),
            PackageSubcommand::Download {
                pkg_id,
                version,
                project_dir,
            } => package_download(pkg_id, version, project_dir),
            PackageSubcommand::List {
                json,
                name,
                lib_type,
            } => package_list(json, name, lib_type),
            PackageSubcommand::Cache { json, name } => package_cache(json, name),
            PackageSubcommand::Delete { project_dir } => package_delete(project_dir),
        }
    }
}
